import numpy as np
import os
import csv
from collections import Counter

# 一、读取数据（增强容错）
def load_data(file_path):
    data = []
    with open(file_path, 'r', encoding='utf-8') as f:
        reader = csv.reader(f)
        for row in reader:
            if len(row) != 5:
                continue  # 忽略格式不对的行
            try:
                features = list(map(float, row[:4]))
                label = row[4].strip()  # 去除空格和换行符
                data.append((features, label))
            except ValueError:
                print(f"跳过非数值行: {row}")
                continue
    # 输出加载结果
    print(f"加载完成：{len(data)}个样本，4个特征")
    return data

# 二、划分训练集和测试集
def train_test_split(data, test_size=0.2, random_state=42):
    np.random.seed(random_state)
    indices = np.random.permutation(len(data))
    split_idx = int(len(data) * (1 - test_size))
    train_indices = indices[:split_idx]
    test_indices = indices[split_idx:]
    train_data = [data[i] for i in train_indices]
    test_data = [data[i] for i in test_indices]
    # 输出划分结果
    print(f"训练集：{len(train_data)}个，测试集：{len(test_data)}个")
    return train_data, test_data

# 三、计算欧氏距离（确保类型转换）
def euclidean_distance(x1, x2):
    x1 = np.array(x1)
    x2 = np.array(x2)
    return np.sqrt(np.sum((x1 - x2) **2))

# 四、KNN 分类器
def knn_predict(train_data, test_sample, k=3):
    distances = []
    for train_sample in train_data:
        train_features, train_label = train_sample
        dist = euclidean_distance(test_sample, train_features)
        distances.append((dist, train_label))
    distances.sort(key=lambda x: x[0])
    nearest_neighbors = distances[:k]
    labels = [label for _, label in nearest_neighbors]
    most_common = Counter(labels).most_common(1)
    return most_common[0][0]

# 五、评估准确率（新增训练集准确率计算）
def evaluate_accuracy(data, train_data, k=3):
    correct = 0
    for sample, true_label in data:
        predicted_label = knn_predict(train_data, sample, k=k)
        if predicted_label == true_label:
            correct += 1
    accuracy = correct / len(data)
    return accuracy

# 六、主函数
def main():
    file_path = r'D:\Python学习\python01\knn_iris\iris.data' 
    
    data = load_data(file_path)
    train_data, test_data = train_test_split(data, test_size=0.2, random_state=42)
    
    k = 3
    print(f"KNN模型构建完成（k={k}）")
    
    # 计算训练集准确率
    train_accuracy = evaluate_accuracy(train_data, train_data, k=k)
    print(f"训练集准确率：{train_accuracy:.4f}")
    
    # 计算测试集准确率
    test_accuracy = evaluate_accuracy(test_data, train_data, k=k)
    print(f"测试集准确率：{test_accuracy:.4f}")

if __name__ == "__main__":
    main()